﻿namespace SageKing.Blazor.OpenIdService.Services;

using System.Security.Claims;
using System.Threading.Tasks;
using AntDesign;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage;
using Microsoft.Extensions.Options;
using SageKing.Core.Extensions;

public class CustomAuthenticationService(
    ProtectedLocalStorage _protectedStore,
    [FromKeyedServices(HttpClientConsts.ClientKey)] IAccountApiClient authService,
    OpenIddictClientService openIddictClientService,
    IOptions<OpenIdServerOptions> option,
    ICancelSource cancelSource)
{
    public event Action<ClaimsPrincipal>? UserChanged;
    private ClaimsPrincipal? currentUser;

    public ClaimsPrincipal User
    {
        get { return currentUser ?? new(); }
        set
        {
            currentUser = value;

            if (UserChanged is not null)
            {
                UserChanged(currentUser);
            }
        }
    }
    public OpenIdServerOptions ServerOption
    {
        get
        {
            return option.Value;
        }
    }
    /// <summary>
    /// 账号密码登录
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    public async Task<(SignInResultVM success, string msg)> SignIn(LoginInput model)
    {
        var result = await authService.PasswordSignInAsync(new LoginViewModel() { UserName = model.Email, Password = model.Password });

        if (!result.Succeeded)
        {
            return (result, "失败");
        }
        try
        {
            var gettoken = await GetTokenAsync();
            result.Token = gettoken;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
        var checkResult = await CheckLogin(result);
        return checkResult;
    }
    public async Task<(SignInResultVM success, string msg)> CheckLogin(SignInResultVM result)
    {
        var newUser = result.User.DictionaryToClaimsPrincipal();
        await _protectedStore.SetAsync(LocalStorageConsts.UserSessionKey, new UserSession()
        {
            UserName = newUser.GetUserName(),
            Data = result.User,
            Token = "demo",
            RefreshToken = "demo",
        });

        User = newUser;

        return (result, "success");
    }

    public async Task<string> GetToken()
    {
        var userSessionStorageResult = await _protectedStore.GetAsync<UserSession>(LocalStorageConsts.UserSessionKey);
        var userSession = userSessionStorageResult.Success ? userSessionStorageResult.Value : null;
        if (userSession.IsNotNull())
        {
            return userSession.Token;
        }
        else
        {
            return "";
        }
    }

    public async Task<string> GetTokenAsync()
    {
        var result = await openIddictClientService.AuthenticateWithClientCredentialsAsync(new());
        return result.AccessToken;
    }

    public async Task<bool> SignOut()
    {
        await _protectedStore.DeleteAsync(LocalStorageConsts.UserSessionKey);
        cancelSource?.value?.Cancel();
        User = new ClaimsPrincipal();
        return true;
    }
}